package util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import java.util.Hashtable;

public class MessagingUtil {
    private final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";
    private final static String INIT_CTX = "t3://localhost:7001";
    private final static String JMS_FACTORY="QCF";

    private Logger logger = LoggerFactory.getLogger(MessagingUtil.class);

    private static InitialContext context;
    private static QueueConnectionFactory connectionFactory;

    private QueueConnection connection;
    private QueueSession session;

    /***************************************************************************************/
    /*
     * Static initialisation
     */
    static {
        context = getInitialContext(INIT_CTX);
        try {
            connectionFactory = (QueueConnectionFactory) context.lookup(JMS_FACTORY);
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
    }

    private static InitialContext getInitialContext(String url)
    {
        // Using of interface Map<String, String> is not supported by InitialContext,
        // hence Hashtable implementation is used
        Hashtable<String, String> env = new Hashtable<String, String>();
        // Name of provider
        env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);
        // Where provider is to be found
        env.put(Context.PROVIDER_URL, url);
        try {
            return new InitialContext(env);
        } catch (NamingException ex) {
            throw new RuntimeException(ex);
        }
    }

    /******************************************************************************************/
    /*
     * Constructor. Creates connection and session.
     */

    public MessagingUtil() {
        try {

            connection = connectionFactory.createQueueConnection();
            session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);

        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }


    /*
     * Starts connection.
     */

    public void startConnection() {
        try {
            connection.start();
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    /*
     * Closes session and connection.
     */

    public void closeSession() {
        try {
            session.close();
        } catch (JMSException e) {
            logger.error("Closing of session failed", e);
        } finally {
            try {
                connection.close();
            } catch (JMSException e) {
                logger.error("Closing of connection failed", e);
            }
        }
    }


    public Queue createQueue(String queueName) {
        try {
            return (Queue) context.lookup(queueName);
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
    }

    public Queue createTempQueue() {
        try {
            return session.createTemporaryQueue();
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    public QueueSender createSender(Queue queue) {
        try {
            return session.createSender(queue);
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    public QueueReceiver createReceiver(Queue queue) {
        try {
            return session.createReceiver(queue);
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    public void closeSender(QueueSender sender) {
        try {
            sender.close();
        } catch (JMSException e) {
            logger.error("Closing of sender failed", e);
            //throw new RuntimeException(e);
        }
    }

    public void closeReceiver(QueueReceiver receiver) {
        try {
            receiver.close();
        } catch (JMSException e) {
            //throw new RuntimeException(e);
            logger.error("Closing of receiver failed", e);
        }
    }

    public TextMessage createMessage() {
        try {
            return session.createTextMessage();
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    public void sendMessage(QueueSender sender, String text, Queue replyTo) {
        try {
            TextMessage message = session.createTextMessage();
            message.setText(text);
            message.setJMSReplyTo(replyTo);

            sender.send(message);
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    public String receiveMessage(QueueReceiver receiver) {
        try {
            TextMessage reply = (TextMessage) receiver.receive();
            return reply.getText();
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }


}
